home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-02
/
vmath10.zip
/
VMATH10.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1991-05-21
|
19KB
|
535 lines
{--------------------------------> Vmath <---------------------------------}
{ This unit contains vector and matrix procedures and functions for TURBO- }
{ PASCAL, partly written as inline assembler code for a 387 coprocessor. }
{ They are about two to three times faster than the equivalent "pure PASCAL" }
{ code. }
{ Known features/limitations/bugs etc.: }
{ - The unit has been written with TP6.0 on an 386SX/IIT387SX machine }
{ - The procedure MulM4V4 needs an IIT coprocessor }
{ - The 287 coprocessor needs additional FWAIT commands in of strategic }
{ places all over the code, since I don't have one I didn't bother. }
{ - All routines PUSH DS on entry, use long pointers (You don't want to }
{ be limited to 64K won't You ?) for operand access and POP DS on exit }
{ - No testing of the routines has been carried out except that they work }
{ fine and fast in my application - NO WARRANTY ! }
{ - I wrote the routines as I needed them (or as I wanted to find out how to }
{ do it, in the case of MulM4V4) but at least the Vector3 operations are }
{ quite complete by now. If I find the time some more Matrix3 code may }
{ follow. }
{----------------------------------------------------------------------------}
{ These routines contain no special artifice, but are straightforward }
{ coded "mathematical common knowledge", so everybody is free to copy }
{ and modify the whole unit or parts of it. And remember: Distributing }
{ sourcecode advances the "Art of Computing" by allowing others to learn }
{ from Your mistakes ! }
{----------------------------------------------------------------------------}
{ I would be pleased to get some feedback (comments/additions/questions or }
{ even a sample application using this unit) from users of Vmath -preferably }
{ via Email - Internet: mowl@cc.flinders.edu.au }
{ }
{ _--_|\ Wolfgang Lieff }
{ / \ Flinders Institute for Atmospheric and Marine Sciences }
{ \_.--x_/ Bedford Park , South Australia 5042 }
{ v }
{----------------------------------------------------------------------------}
{ Version 1.0 of 20/05/1991 by Wolfgang Lieff }
{----------------------------------------------------------------------------}
unit Vmath10;
interface
type Matrix4 = array[0..3,0..3] of double;
Vector4 = array[0..3] of double;
Matrix3 = array[0..2,0..2] of double;
Vector3 = array[0..2] of double;
const
ZeroV3 : Vector3 = (0.0,0.0,0.0);
XunityV3 : Vector3 = (1.0,0.0,0.0);
YunityV3 : Vector3 = (0.0,1.0,0.0);
ZunityV3 : Vector3 = (0.0,0.0,1.0);
{----------------------------------------------------------------------------}
procedure DirectionV3(P1,P2:Vector3; var R:Vector3);
{ =========== }
{ Function Calculates the unity direction vector from P1 to P2 }
{ }
{ Result type Vector3 }
{----------------------------------------------------------------------------}
procedure MulV3V3(V1,V2:Vector3; var R:Vector3);
{ ======= }
{ Function Multiplies the components of two vectors }
{ }
{ Result type Vector3 }
{----------------------------------------------------------------------------}
function MulV3(V1,V2:Vector3):double;
{ ===== }
{ Function Scalar multiplication (dot product) of two vectors }
{ }
{ Result type double }
{----------------------------------------------------------------------------}
procedure CrossV3(V1,V2:Vector3; var R:Vector3);
{ ======= }
{ Function Vector multiplication (cross product) of two vectors }
{ }
{ Result type Vector3 }
{----------------------------------------------------------------------------}
procedure NormalizeV3(var V:Vector3);
{ =========== }
{ Function Transforms a vector into a unity vector with the same }
{ direction }
{ }
{ Result type Vector }
{----------------------------------------------------------------------------}
function AbsV3(V:Vector3):double;
{ ===== }
{ Function Returns the length of a vector }
{ }
{ Result type double }
{----------------------------------------------------------------------------}
function QuickAbsV3(V:Vector3):double;
{ ========== }
{ Function Returns a rough estimate of the length of a vector }
{ by simply adding the absolute values of the components}
{ }
{ Result type double }
{----------------------------------------------------------------------------}
procedure MulV3D(V:Vector3; S:double; var R:Vector3);
{ ====== }
{ Function Multiplies the components of a vector with a scalar }
{ }
{ Result type Vector3 }
{----------------------------------------------------------------------------}
procedure DivV3D(V:Vector3; S:double; var R:Vector3);
{ ====== }
{ Function Divides the components of a vector by a scalar }
{ }
{ Result type double }
{----------------------------------------------------------------------------}
procedure DivV3V3(V1,V2:Vector3; R:Vector3);
{ ======= }
{ Function Divides the components of two vectors }
{ }
{ Result type double }
{----------------------------------------------------------------------------}
procedure AddV3(V1,V2:Vector3; var R:Vector3);
{ ===== }
{ Function Adds two vectors }
{ }
{ Result type Vector3 }
{----------------------------------------------------------------------------}
procedure SubV3(V1,V2:Vector3; var R:Vector3);
{ ===== }
{ Function Subtracts two vectors }
{ }
{ Result type Vector3 }
{----------------------------------------------------------------------------}
procedure DtoV3(X,Y,Z:double; var V:Vector3);
{ ===== }
{ Function Copies three scalars into the components of a vector }
{ }
{ Result type Vector3 }
{----------------------------------------------------------------------------}
procedure InvertV3(var V:Vector3);
{ ======== }
{ Function Inverts the sign of all vector components }
{ }
{ Result type Vector3 }
{----------------------------------------------------------------------------}
procedure RandomUnitV3(var V:Vector3);
{ ============ }
{ Function Generates a random unit vector }
{ }
{ Result type Vector3 }
{----------------------------------------------------------------------------}
procedure MulM4V4 (A:Matrix4; B:Vector4; var C:Vector4);
{ ======= }
{ Function Multiplies a 4x4 matrix with a 4-element vector }
{ }
{ Result type Vector4 }
{ }
{ Remark Uses the register page switching and matrix functions }
{ of the IIT coprocessors }
{----------------------------------------------------------------------------}
function Det3V3(V1,V2,V3:Vector3):double;
{ ====== }
{ Function Calculates the determinant of a matrix who's columns }
{ are formed by three vectors }
{ }
{ Result type double }
{----------------------------------------------------------------------------}
implementation
procedure MulM4V4(A:Matrix4; B:Vector4; var C:Vector4); assembler;
asm
PUSH DS
FINIT
LDS SI,dword ptr A
DW $EBDB { The first IIT switch opcode }
FLD qword ptr[SI+$10]
FLD qword ptr[SI+$30]
FLD qword ptr[SI+$50]
FLD qword ptr[SI+$70]
FLD qword ptr[SI+$18]
FLD qword ptr[SI+$38]
FLD qword ptr[SI+$58]
FLD qword ptr[SI+$78]
FINIT
DW $EADB { The second IIT switch opcode }
FLD qword ptr[SI]
FLD qword ptr[SI+$20]
FLD qword ptr[SI+$40]
FLD qword ptr[SI+$60]
FLD qword ptr[SI+$08]
FLD qword ptr[SI+$28]
FLD qword ptr[SI+$48]
FLD qword ptr[SI+$68]
FINIT
LDS SI,dword ptr B
DW $E8DB { And the last IIT switch opcode }
FLD qword ptr[SI+$18]
FLD qword ptr[SI+$10]
FLD qword ptr[SI+$08]
FLD qword ptr[SI]
LDS SI,dword ptr C
DW $F1DB { This IIT opcode triggers the operation }
FSTP qword ptr[SI]
FSTP qword ptr[SI+$08]
FSTP qword ptr[SI+$10]
FSTP qword ptr[SI+$18]
POP DS
end;
function Det3V3(V1,V2,V3:Vector3):double; assembler;
asm
PUSH DS
LDS SI,dword ptr V3
FLD qword ptr[SI+$10]
FLD qword ptr[SI+$08]
LDS SI,dword ptr V2
FLD qword ptr[SI+$10]
FLD qword ptr[SI+$08]
FMULP ST(3),ST(0)
FMULP ST(1),ST(0)
FSUBP ST(1),ST(0)
LDS SI,dword ptr V1
FLD qword ptr [SI]
FMULP ST(1),ST(0)
FLD qword ptr [SI+$08]
FLD qword ptr [SI+$10]
LDS SI,dword ptr V3
FLD qword ptr [SI+$08]
FLD qword ptr [SI+$10]
FMULP ST(3),ST(0)
FMULP ST(1),ST(0)
FSUBP ST(1),ST(0)
LDS SI,dword ptr V2
FLD qword ptr [SI]
FMULP ST(1),ST(0)
FSUBP ST(1),ST(0)
LDS SI,dword ptr V2
FLD qword ptr [SI+$10]
FLD qword ptr [SI+$08]
LDS SI,dword ptr V1
FLD qword ptr [SI+$10]
FLD qword ptr [SI+$08]
FMULP ST(3),ST(0)
FMULP ST(1),ST(0)
FSUBP ST(1),ST(0)
LDS SI,dword ptr V3
FLD qword ptr [SI]
FMULP ST(1),ST(0)
FADDP ST(1),ST(0)
POP DS
end;
procedure InvertV3(var V:Vector3); assembler;
asm
PUSH DS
PUSH AX
LDS SI,dword ptr V
MOV AL,$80
XOR [SI+$07],AL
XOR [SI+$0F],AL
XOR [SI+$17],AL
POP AX
POP DS
end;
procedure DtoV3(X,Y,Z:double; var V:Vector3); assembler;
asm
PUSH DS
LDS SI,dword ptr V
FLD X
FSTP qword ptr [SI]
FLD Y
FSTP qword ptr [SI+$08]
FLD Z
FSTP qword ptr [SI+$10]
POP DS
end;
procedure SubV3(V1,V2:Vector3; var R:Vector3); assembler;
asm
PUSH DS
LDS SI,dword ptr V1
FLD qword ptr[SI]
FLD qword ptr[SI+$08]
FLD qword ptr[SI+$10]
LDS SI,dword ptr V2
FLD qword ptr[SI]
FLD qword ptr[SI+$08]
FLD qword ptr[SI+$10]
FSUBP ST(3),ST(0)
FSUBP ST(3),ST(0)
FSUBP ST(3),ST(0)
LDS SI,dword ptr R
FSTP qword ptr[SI+$10]
FSTP qword ptr[SI+$08]
FSTP qword ptr[SI]
POP DS
end;
procedure AddV3(V1,V2:Vector3; var R:Vector3); assembler;
asm
PUSH DS
LDS SI,dword ptr V1
FLD qword ptr[SI]
FLD qword ptr[SI+$08]
FLD qword ptr[SI+$10]
LDS SI,dword ptr V2
FLD qword ptr[SI]
FLD qword ptr[SI+$08]
FLD qword ptr[SI+$10]
FADDP ST(3),ST(0)
FADDP ST(3),ST(0)
FADDP ST(3),ST(0)
LDS SI,dword ptr R
FSTP qword ptr[SI+$10]
FSTP qword ptr[SI+$08]
FSTP qword ptr[SI]
POP DS
end;
procedure MulV3V3(V1,V2:Vector3; var R:Vector3); assembler;
asm
PUSH DS
LDS SI,dword ptr V1
FLD qword ptr[SI]
FLD qword ptr[SI+$08]
FLD qword ptr[SI+$10]
LDS SI,dword ptr V2
FLD qword ptr[SI]
FLD qword ptr[SI+$08]
FLD qword ptr[SI+$10]
FMULP ST(3),ST(0)
FMULP ST(3),ST(0)
FMULP ST(3),ST(0)
LDS SI,dword ptr R
FSTP qword ptr[SI+$10]
FSTP qword ptr[SI+$08]
FSTP qword ptr[SI]
POP DS
end;
procedure DivV3V3(V1,V2:Vector3; R:Vector3); assembler;
asm
PUSH DS
LDS SI,dword ptr V1
FLD qword ptr[SI]
FLD qword ptr[SI+$08]
FLD qword ptr[SI+$10]
LDS SI,dword ptr V2
FLD qword ptr[SI]
FLD qword ptr[SI+$08]
FLD qword ptr[SI+$10]
FDIVP ST(3),ST(0)
FDIVP ST(3),ST(0)
FDIVP ST(3),ST(0)
LDS SI,dword ptr R
FSTP qword ptr[SI+$10]
FSTP qword ptr[SI+$08]
FSTP qword ptr[SI]
POP DS
end;
procedure MulV3D(V:Vector3; S:double; var R:Vector3); assembler;
asm
PUSH DS
LDS SI,dword ptr V
FLD qword ptr[SI]
FLD qword ptr[SI+$08]
FLD qword ptr[SI+$10]
FLD S
FMUL ST(3),ST(0)
FMUL ST(2),ST(0)
FMULP ST(1),ST(0)
LDS SI,dword ptr R
FSTP qword ptr[SI+$10]
FSTP qword ptr[SI+$08]
FSTP qword ptr[SI]
POP DS
end;
procedure DivV3D(V:Vector3; S:double; var R:Vector3); assembler;
asm
PUSH DS
LDS SI,dword ptr V
FLD qword ptr[SI]
FLD qword ptr[SI+$08]
FLD qword ptr[SI+$10]
FLD S
FDIV ST(3),ST(0)
FDIV ST(2),ST(0)
FDIVP ST(1),ST(0)
LDS SI,dword ptr R
FSTP qword ptr[SI+$10]
FSTP qword ptr[SI+$08]
FSTP qword ptr[SI]
POP DS
end;
function AbsV3(V:Vector3):double; assembler;
asm
PUSH DS
LDS SI,dword ptr V
FLD qword ptr[SI]
FLD ST(0)
FMULP ST(1),ST(0)
FLD qword ptr[SI+$08]
FLD ST(0)
FMULP ST(1),ST(0)
FADDP ST(1),ST(0)
FLD qword ptr[SI+$10]
FLD ST(0)
FMULP ST(1),ST(0)
FADDP ST(1),ST(0)
FSQRT
POP DS
end;
function QuickAbsV3(V:Vector3):double; assembler;
asm
PUSH DS
LDS SI,dword ptr V
FLD qword ptr[SI]
FABS
FLD qword ptr[SI+$08]
FABS
FADDP ST(1),ST(0)
FLD qword ptr[SI+$10]
FABS
FADDP ST(1),ST(0)
POP DS
end;
procedure NormalizeV3(var V:Vector3); assembler;
asm
PUSH DS
LDS SI,dword ptr V
FLD qword ptr[SI]
FLD qword ptr[SI+$08]
FLD qword ptr[SI+$10]
FLD ST(2)
FLD ST(0)
FMULP ST(1),ST(0)
FLD ST(2)
FLD ST(0)
FMULP ST(1),ST(0)
FADDP ST(1),ST(0)
FLD ST(1)
FLD ST(0)
FMULP ST(1),ST(0)
FADDP ST(1),ST(0)
FSQRT
FDIV ST(3),ST(0)
FDIV ST(2),ST(0)
FDIVP ST(1),ST(0)
FSTP qword ptr[SI+$10]
FSTP qword ptr[SI+$08]
FSTP qword ptr[SI]
POP DS
end;
function MulV3(V1,V2:Vector3):double; assembler;
asm
PUSH DS
LDS SI,dword ptr V1
FLD qword ptr[SI]
FLD qword ptr[SI+$08]
FLD qword ptr[SI+$10]
LDS SI,dword ptr V2
FLD qword ptr[SI]
FLD qword ptr[SI+$08]
FLD qword ptr[SI+$10]
FMULP ST(3),ST(0)
FMULP ST(3),ST(0)
FMULP ST(3),ST(0)
FADDP ST(1),ST(0)
FADDP ST(1),ST(0)
POP DS
end;
procedure CrossV3(V1,V2:Vector3; var R:Vector3); assembler;
asm
PUSH DS
LDS SI,dword ptr V1
FLD qword ptr[SI]
FLD qword ptr[SI+$08]
FLD qword ptr[SI+$10]
LDS SI,dword ptr V2
FLD qword ptr[SI]
FLD qword ptr[SI+$08]
FLD qword ptr[SI+$10]
LDS SI,dword ptr R
FLD ST(4)
FMUL ST(0),ST(1)
FLD ST(2)
FMUL ST(0),ST(5)
FSUBP ST(1),ST(0)
FSTP qword ptr[SI]
FLD ST(3)
FMUL ST(0),ST(3)
FLD ST(6)
FMUL ST(0),ST(2)
FSUBP ST(1),ST(0)
FSTP qword ptr[SI+$08]
FLD ST(5)
FMUL ST(0),ST(2)
FLD ST(3)
FMUL ST(0),ST(6)
FSUBP ST(1),ST(0)
FSTP qword ptr[SI+$10]
FINIT
POP DS
end;
procedure DirectionV3(P1,P2:Vector3; var R:Vector3);
begin
SubV3(P2,P1,R);
NormalizeV3(R);
end;
procedure RandomUnitV3(var V:Vector3);
begin
DtoV3(Random-0.5,Random-0.5,Random-0.5,V);
NormalizeV3(V);
end;
end.